home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 May: Tool Chest / Developer CD Series Tool Chest (Apple Computer)(May 1999).iso / What's New? / • What was new 03⁄99 / Tool Chest / Sample Code / Eject PC Cards Location Module / Sources / EjectPCCardModule.c next >
Encoding:
Text File  |  1998-12-22  |  19.7 KB  |  683 lines  |  [TEXT/CWIE]

  1. /*
  2.      File:        Sample.c
  3.  
  4.      Contains:    Location Manager SDK Sample main code...
  5.  
  6.      Version:    ALM SDK 2.0
  7.                  Package:    Location Manager SDK 2.0
  8.  
  9.      Copyright:    © 1996-1997 by Apple Computer, Inc.
  10.                  All rights reserved.
  11.  
  12.      Bugs?:        Please include the the file and version information (from above) with
  13.                  the problem description.  Developers belonging to one of the Apple
  14.                  developer programs can submit bug reports to:
  15.  
  16.                      devsupport@apple.com
  17.  
  18. */
  19.  
  20. // ------------------------------------------------------------------------------------------------- 
  21.  
  22. #include    <ConditionalMacros.h>
  23.  
  24. // We recommend using the most updated headers currently available; at this writing, that is
  25. // Universal Headers 3.0.1.  More recent editions should work as well; if you want to use older
  26. // headers for some reason, it should be possible, but you're on your own and other parts of this
  27. // sample may need to change...
  28.  
  29. #if        !defined (UNIVERSAL_INTERFACES_VERSION) || (UNIVERSAL_INTERFACES_VERSION < 0x0301)
  30.  
  31.     #error    "Please use header files 3.0.1 or newer"
  32.  
  33. #endif    // updated headers...
  34.  
  35. // Having gotten _that_ out of the way, let's be sure that nobody fiddled with the project
  36. // settings by accident...
  37.  
  38. #if            !TARGET_CPU_68K | TARGET_RT_MAC_CFM
  39.  
  40.     #error        This project MUST be classic 68K!
  41.  
  42. #endif        // not 68K classic build
  43.  
  44. // ------------------------------------------------------------------------------------------------- 
  45.  
  46. // Module Include...
  47.  
  48. #include    "EjectPCCardModule.h"
  49.  
  50. // MacOS Includes...
  51.  
  52. #define        ALM_BASENAME()
  53.  
  54. #include    <Components.h>
  55. #include    <Fonts.h>
  56. #include    <LocationManager.k.h>
  57. #include    <PLStringFuncs.h>
  58. #include    <Resources.h>
  59. #include    <TextUtils.h>
  60.  
  61. // ------------------------------------------------------------------------------------------------- 
  62.  
  63. // Module-specific defines...
  64.  
  65. #define        kModuleVersion                1
  66.  
  67. // ------------------------------------------------------------------------------------------------- 
  68.  
  69. // Readability Constants...
  70.  
  71. #define        kInvalidFunction            ((ComponentFunctionUPP) -1)
  72.  
  73. #define        kDefaultINTLresources        NULL
  74. #define        kNoSeconds                    false
  75.  
  76. #define        kAllocateMemory                NULL
  77. #define        kPlaceInFront                (WindowPtr)-1
  78.  
  79. #define        kUseStandardFilterProc        NULL
  80.  
  81. // ------------------------------------------------------------------------------------------------- 
  82.  
  83. // Local prototypes...
  84.  
  85. static Boolean
  86. CallSupported (SInt16 selector);
  87.     // Return true if the specified selector code is one this module supports...
  88. static ComponentResult
  89. HandleComponentManagerCall (ComponentParameters* params, SInt16 selector);
  90.     // Dispatch a component manager call (selector < 0)...
  91. static ComponentResult
  92. HandleLocationManagerCall (ComponentParameters* params, SInt16 selector);
  93.     // Dispatch a Location Manager specific call...
  94.  
  95. // Component prototypes...
  96.  
  97. static pascal ComponentResult
  98. Open (ComponentInstance self);
  99.     // Initialize the modules's global variables, etc...
  100. static pascal ComponentResult 
  101. Close (ComponentInstance self);
  102.     // Deinitialize the modules's global variables...
  103.  
  104. OSErr Call_ResourcePPC (ResType pResType, short pResID, long params);
  105.  
  106. // ------------------------------------------------------------------------------------------------- 
  107.  
  108. // Main entry point (interface as expected by component manager)...
  109.  
  110. pascal ComponentResult
  111. main (ComponentParameters* params, Handle storage) {
  112.  
  113. #ifndef    __SC__
  114. #pragma unused (storage)
  115. #endif    // __SC__
  116.  
  117.     // We dispatch the calls from here; also, for ALM calls, we'll make sure the current
  118.     // resource fork is ours...
  119.  
  120.     ComponentResult            result;
  121.     SInt16                    selector     = params->what;
  122.  
  123.     if (selector < 0) {
  124.         // Component manager request codes are negative...
  125.         result = HandleComponentManagerCall (params, selector);
  126.     } else {
  127.         // ALM selectors...
  128.         result = HandleLocationManagerCall (params, selector);
  129.     } // if
  130.             
  131.     return result;
  132.  
  133. } // main
  134.  
  135. // ------------------------------------------------------------------------------------------------- 
  136.  
  137. static Boolean
  138. CallSupported (SInt16 selector) {
  139.  
  140.     Boolean        response;
  141.  
  142.     switch (selector) {
  143.         case kALMGetCurrentSelect:
  144.         case kALMSetCurrentSelect:
  145.         case kALMCompareSettingSelect:
  146.         case kALMDescribeSettingSelect:
  147.         case kALMDescribeErrorSelect:
  148.         case kALMEditSettingSelect:
  149.         case kALMGetInfoSelect:
  150.         case kALMGetScriptInfoSelect:
  151.             response = true;
  152.             break;
  153.         default:
  154.             response = false;
  155.             break;
  156.     } // switch
  157.  
  158.     return response;
  159.  
  160. } // CallSupported
  161.  
  162. // ------------------------------------------------------------------------------------------------- 
  163.  
  164. static ComponentResult
  165. HandleComponentManagerCall (ComponentParameters* params, SInt16 selector) {
  166.  
  167.     ComponentResult            result     = (ComponentResult) noErr;
  168.     ComponentFunctionUPP     func     = NULL;
  169.  
  170.     switch (selector) {
  171.  
  172.         case kComponentOpenSelect:
  173.             func = (ComponentFunctionUPP) Open;
  174.             break;
  175.         case kComponentCloseSelect:
  176.             func = (ComponentFunctionUPP) Close;
  177.             break;
  178.         case kComponentCanDoSelect:
  179.             result = CallSupported (*(SInt16*) params->params);
  180.             break;
  181.         case kComponentVersionSelect:
  182.             result = kModuleVersion;
  183.             break;
  184.         case kComponentRegisterSelect:
  185.             result = false;            // false means "yes, please register me"    
  186.             break;
  187.         case kComponentTargetSelect :
  188.         case kComponentUnregisterSelect :
  189.             result = badComponentSelector;
  190.             break;
  191.             
  192.     } // switch
  193.     
  194.     if (func != NULL) {
  195.         result = CallComponentFunction (params, func);
  196.     } // if
  197.  
  198.     return result;
  199.  
  200. } // HandleComponentManagerCall
  201.  
  202. // ------------------------------------------------------------------------------------------------- 
  203.  
  204. static ComponentResult
  205. HandleLocationManagerCall (ComponentParameters* params, SInt16 selector) {
  206.  
  207.     ComponentResult            result     = (ComponentResult) noErr;
  208.     ComponentFunctionUPP     func     = NULL;
  209.  
  210.     switch (selector) {
  211.     
  212.         case kALMGetCurrentSelect:
  213.             func = (ComponentFunctionUPP) GetCurrent;
  214.             break;
  215.         case kALMSetCurrentSelect:
  216.             func = (ComponentFunctionUPP) SetCurrent;
  217.             break;
  218.         case kALMCompareSettingSelect:
  219.             func = (ComponentFunctionUPP) CompareSetting;
  220.             break;
  221.         case kALMEditSettingSelect:
  222.             func = (ComponentFunctionUPP) EditSetting;
  223.             break;
  224.         case kALMDescribeSettingSelect:
  225.             func = (ComponentFunctionUPP) DescribeSetting;
  226.             break;
  227.         case kALMDescribeErrorSelect:
  228.             func = (ComponentFunctionUPP) DescribeError;
  229.             break;
  230.         case kALMGetScriptInfoSelect:
  231.             func = (ComponentFunctionUPP) GetScriptInfo;
  232.             break;
  233.         case kALMGetInfoSelect:
  234.             func = (ComponentFunctionUPP) GetInfo;
  235.             break;
  236.         default:
  237.             func = kInvalidFunction;
  238.             break;
  239.             
  240.     } // switch
  241.  
  242.     if (func == kInvalidFunction) {
  243.         result = badComponentSelector;
  244.     } else if (func != NULL) {
  245.         result = CallComponentFunction (params, func);
  246.     } // if
  247.  
  248.     return result;
  249.  
  250. } // HandleLocationManagerCall
  251.  
  252. // ------------------------------------------------------------------------------------------------- 
  253.  
  254. static    pascal ComponentResult
  255. Open (ComponentInstance self) {
  256.  
  257.     // Keep the Open routine lightweight, and only fail in the case of dire
  258.     // emergencies that indicate a major problem; under ALM 2.0, you might wish to return an
  259.     // error here to quietly suppress your module from being usable--for example if you require
  260.     // Infrared hardware found only on some models of computer--but it is generally better to
  261.     // _succeed_ here and describe an _error_ from your GetCurrent call...
  262.  
  263.     // Since we are an action module, we have no state to remember.  The only thing we
  264.     // need to keep track of is our resource fork refnum so that we can get our resources if
  265.     // needed.  No need for a complicated globals structure for that, it fits nicely into
  266.     // 32 bits (with 16 to spare), so just set our instance storage to our resource refnum.
  267.     SetComponentInstanceStorage (self, (Handle)OpenComponentResFile ((Component) self));
  268.  
  269.     return (ComponentResult) ResError ();
  270.     
  271. } // Open
  272.  
  273. // ------------------------------------------------------------------------------------------------- 
  274.  
  275. static    pascal ComponentResult
  276. Close (ComponentInstance self) {
  277.  
  278.     // Always make sure to close your resource fork before exiting a component, otherwise
  279.     // really bad things will happen to the foreground application.
  280.     CloseComponentResFile ((short)GetComponentInstanceStorage (self));
  281.  
  282.     return (ComponentResult) noErr;
  283.     
  284. } // Close
  285.  
  286. // ------------------------------------------------------------------------------------------------- 
  287.  
  288. static pascal ComponentResult    
  289. GetCurrent (Handle setting) {
  290.  
  291.     OSErr                err        = noErr;
  292.     long                attributes;
  293.  
  294.     // Make sure that the system has PC Card Manager 3.0 or later installed so that we don't
  295.     // run on a system that a) isn't PPC, and b) doesn't support the PC Card 3.0 API.
  296.     err = Gestalt (gestaltPCCard, &attributes);
  297.     if (err == noErr && !(attributes & (1L << gestaltPCCardFamilyPresent))) {
  298.         // Return a descriptive error, "We require PC Card Manager 3.0 or later"
  299.         err = kNeedPCCard3Err;
  300.     } else if (err == gestaltUndefSelectorErr) {
  301.         // Return a descriptive error, "This machine doesn't even support PC Cards"
  302.         err = kNeedPCCardsErr;
  303.     }
  304.  
  305.     if (err == noErr) {
  306.         SetHandleSize ((Handle) setting, sizeof (SettingRec));
  307.         err = MemError ();
  308.     }
  309.  
  310.     if (err == noErr) {
  311.         (**(SettingHandle)setting).version = kModuleVersion;
  312.         (**(SettingHandle)setting).slot = kNoSlotsID;
  313.     }
  314.  
  315.     return (ComponentResult) err;
  316.  
  317. } // GetCurrent
  318.  
  319. // ------------------------------------------------------------------------------------------------- 
  320.  
  321. static pascal ComponentResult
  322. SetCurrent (Handle setting, ALMRebootFlags* flags) {
  323.  
  324.     OSErr                err                = noErr;
  325.     long                attributes;
  326.  
  327.     // Hopefully this code won't ever detect that we are on an unsupported system, but perhaps
  328.     // the user might have imported a setting from a PowerBook to a desktop machine, and we don't
  329.     // want to crash.
  330.  
  331.     // Make sure that the system has PC Card Manager 3.0 or later installed so that we don't
  332.     // run on a system that a) isn't PPC, and b) doesn't support the PC Card 3.0 API.
  333.     err = Gestalt (gestaltPCCard, &attributes);
  334.     if (err == noErr && !(attributes & (1L << gestaltPCCardFamilyPresent))) {
  335.         // Return a descriptive error, "We require PC Card Manager 3.0 or later"
  336.         err = kNeedPCCard3Err;
  337.     } else if (err == gestaltUndefSelectorErr) {
  338.         // Return a descriptive error, "This machine doesn't even support PC Cards"
  339.         err = kNeedPCCardsErr;
  340.     }
  341.  
  342.     // Call a PPC code resource to walk the name registry and eject the desired PC Cards.
  343.     err = Call_ResourcePPC (kPPCCodeResource, kPPCCodeResourceID, (**(SettingHandle)setting).slot);
  344.  
  345.     if (err == noErr) {
  346.         // It either worked and everything is cool...
  347.         *flags = kALMAvailableNow;
  348.     } else {
  349.         // ... or we didn't eject anything and so things remain as they were.
  350.         *flags = kALMNoChange;
  351.     }
  352.  
  353.     return (ComponentResult) err;
  354.  
  355. } // SetCurrent
  356.  
  357. // ------------------------------------------------------------------------------------------------- 
  358.  
  359. static pascal ComponentResult
  360. CompareSetting (Handle setting1, Handle setting2, Boolean* equal) {
  361.  
  362.     // A simple compare tells us if the two settings are the same.
  363.     *equal = ((**(SettingHandle)setting1).slot == (**(SettingHandle)setting2).slot);
  364.  
  365.     return (ComponentResult) noErr;
  366.  
  367. } // CompareSetting
  368.  
  369. // ------------------------------------------------------------------------------------------------- 
  370.  
  371. static pascal ComponentResult
  372. EditSetting (Handle setting) {
  373.  
  374.     OSErr                err                = noErr;
  375.     UInt32                 savedA5;
  376.     QDGlobals            mqd;                    // So we can put up an alert...
  377.     QDGlobalsPtr        moduleQuickdraw = &mqd;
  378.     DialogPtr            theDialog         = NULL;
  379.  
  380.     // In ALM 2.0, if you don't support EditSetting, the control panel will display a default
  381.     // error message if the user tries to edit your setting.  Of course, how to edit the setting
  382.     // is entirely dependant on the content of the setting.  In the case of this sample, we
  383.     // really don't know what the meaning of the preference file is, but we can, at the very least,
  384.     // give the user a more helpful error message...
  385.     
  386.     savedA5 = SetA5 ((UInt32) &moduleQuickdraw);
  387.  
  388.     // Initialize a QD world...
  389.     
  390.     InitGraf (&mqd.thePort);        // always init _our_ QD structure
  391.     InitFonts ();
  392.     InitWindows ();
  393.     InitMenus ();
  394.     TEInit ();
  395.     InitDialogs (NULL);
  396.     InitCursor ();
  397.  
  398.     // Get and display the "which PC Card slot" dialog...
  399.  
  400.     theDialog = GetNewDialog (kEditMessageRsrcID, kAllocateMemory, kPlaceInFront);
  401.  
  402.     if (theDialog != NULL) {
  403.     
  404.         SInt16                itemHit;
  405.         GrafPtr                svPort;
  406.         short                itemType;
  407.         ControlHandle        item;
  408.         Rect                box;
  409.  
  410.         GetPort (&svPort);
  411.         SetPort (theDialog);
  412.         SetDialogDefaultItem (theDialog, kEditOKButton);
  413.         SetDialogCancelItem (theDialog, kEditCancelButton);
  414.  
  415.         if ((**(SettingHandle)setting).slot == kLowerSlotID || (**(SettingHandle)setting).slot == kBothSlotsID) {
  416.             GetDialogItem (theDialog, kLowerPCCardCheckBox, &itemType, &(Handle)item, &box);
  417.             SetControlValue (item, 1);
  418.         }
  419.  
  420.         if ((**(SettingHandle)setting).slot == kUpperSlotID || (**(SettingHandle)setting).slot == kBothSlotsID) {
  421.             GetDialogItem (theDialog, kUpperPCCardCheckBox, &itemType, &(Handle)item, &box);
  422.             SetControlValue (item, 1);
  423.         }
  424.  
  425.         ShowWindow (theDialog);
  426.         
  427.         // Loop until closed; note that, as long as we use the standard filter proc, 
  428.         // the ALM control panel will manage launches and moveable-modal things for us...
  429.         
  430.         do {
  431.             ModalDialog (kUseStandardFilterProc, &itemHit);
  432.             switch (itemHit) {
  433.                 case kEditCancelButton:
  434.                     err = userCanceledErr;
  435.                     break;
  436.                 case kEditOKButton:
  437.                     err = noErr;
  438.                     break;
  439.                 case kUpperPCCardCheckBox:
  440.                 case kLowerPCCardCheckBox:
  441.                     GetDialogItem (theDialog, itemHit, &itemType, &(Handle)item, &box);
  442.                     if (itemType == chkCtrl + ctrlItem) {
  443.                         SetControlValue (item, !GetControlValue (item));
  444.                     }
  445.                     break;
  446.             } // switch
  447.         } while (itemHit != kEditCancelButton && itemHit != kEditOKButton);
  448.  
  449.         if (err == noErr) {
  450.             short    lower, upper;
  451.  
  452.             SetHandleSize ((Handle) setting, sizeof (SettingRec));
  453.             err = MemError ();
  454.  
  455.             if (err == noErr) {
  456.                 GetDialogItem (theDialog, kLowerPCCardCheckBox, &itemType, &(Handle)item, &box);
  457.                 lower = GetControlValue (item);
  458.                 
  459.                 GetDialogItem (theDialog, kUpperPCCardCheckBox, &itemType, &(Handle)item, &box);
  460.                 upper = GetControlValue (item);
  461.                 
  462.                 if (upper && lower) {
  463.                     (**(SettingHandle)setting).slot = kBothSlotsID;
  464.                 } else if (lower) {
  465.                     (**(SettingHandle)setting).slot = kLowerSlotID;
  466.                 } else if (upper) {
  467.                     (**(SettingHandle)setting).slot = kUpperSlotID;
  468.                 } else {
  469.                     // If nothing was checked, then the user doesn't need our module.
  470.                     (**(SettingHandle)setting).slot = kNoSlotsID;
  471.                     err = kModuleNotNeededErr;
  472.                 }
  473.             }
  474.         }
  475.     
  476.         DisposeDialog (theDialog);
  477.         SetPort (svPort);
  478.     
  479.     } else {
  480.     
  481.         err = resNotFound;
  482.     
  483.     } // if
  484.  
  485.     // Restore a5...
  486.  
  487.     (void) SetA5 (savedA5);
  488.  
  489.     return (ComponentResult) err;
  490.  
  491. } // EditSetting
  492.  
  493. // ------------------------------------------------------------------------------------------------- 
  494.  
  495. static pascal ComponentResult
  496. DescribeSetting (Handle setting, CharsHandle text) {
  497.  
  498.     OSErr                err        = noErr;
  499.     Str255                settingDescription;
  500.  
  501.     // Get the description strings "Neither slot", "Both slots", "Upper slot", "Lower slot"
  502.     // The STR# resource is laid out so that our setting's slot+2 value gets the correct resource.
  503.     GetIndString (settingDescription, kDescribeSettingStrings, (**(SettingHandle)setting).slot + 2);
  504.     err = ResError ();
  505.  
  506.     if (err == noErr && settingDescription[0] == 0) {
  507.         err = resNotFound;
  508.     }
  509.  
  510.     if (err == noErr) {
  511.         SetHandleSize (text, settingDescription[0]);
  512.         err = MemError ();
  513.     }
  514.  
  515.     if (err == noErr) {
  516.         BlockMoveData (&(settingDescription[1]), *text, settingDescription[0]);
  517.     }
  518.  
  519.     return (ComponentResult) err;
  520.  
  521. } // DescribeSetting
  522.  
  523. // ------------------------------------------------------------------------------------------------- 
  524.  
  525. static pascal ComponentResult
  526. DescribeError (OSErr lastErr, Str255 errStr) {
  527.  
  528.     OSErr                                err            = noErr;
  529.     short                                stringID;
  530.  
  531.     // Get the error requested.  I'm not sure if we will ever get the resNotFound error, but
  532.     // just in case, we have a description of what it means.
  533.  
  534.     switch (lastErr) {
  535.         case resNotFound:
  536.             stringID = kDescribeResNotFound;
  537.             break;
  538.         case kModuleNotNeededErr:
  539.             stringID = kDescribeNotNeeded;
  540.             break;
  541.         case kNeedPCCard3Err:
  542.             stringID = kDescribeNeedPCCard3;
  543.             break;
  544.         case kNeedPCCardsErr:
  545.             stringID = kDescribeNeedPCCards;
  546.             break;
  547.     }
  548.  
  549.     GetIndString (errStr, kDescribeErrorStrings, stringID);
  550.     err = ResError ();
  551.  
  552.     if (err == noErr && errStr[0] == 0) {
  553.         err = resNotFound;
  554.     }
  555.  
  556.     if (lastErr == err) {
  557.         // Don't get stuck in a loop...
  558.         // I'm not sure if the Location Manager checks this or not, but better safe then sorry.
  559.         // Basically this prevents a never ending stream of resNotFound errors.
  560.         err = noErr;
  561.     }
  562.  
  563.     return (ComponentResult) err;
  564.  
  565. } // DescribeError
  566.  
  567. // ------------------------------------------------------------------------------------------------- 
  568.  
  569. static pascal ComponentResult
  570. GetScriptInfo (ALMScriptManagerInfo* info) {
  571.  
  572.     OSErr                                err            = noErr;
  573.     ALMAltScriptManagerInfoHandle        scriptInfo    = NULL;
  574.  
  575.     // We stored this stuff in a resource, so it can be localized easily; we have to do a bit of
  576.     // translation, though, from the alternate format to the ALM format (fortunately
  577.     // the alternate format is given to us in the headers!)...
  578.     
  579.     scriptInfo = (ALMAltScriptManagerInfoHandle) 
  580.                 GetResource (kALMAltScriptManagerInfoRsrcType, kALMAltScriptManagerInfoRsrcID);
  581.     
  582.     if (scriptInfo != NULL) {
  583.  
  584.         HLock ((Handle) scriptInfo);
  585.         
  586.         info->version         = (**scriptInfo).version;
  587.         info->scriptCode     = (**scriptInfo).scriptCode;
  588.         info->regionCode     = (**scriptInfo).regionCode;
  589.         info->langCode         = (**scriptInfo).langCode;
  590.         info->fontSize         = (**scriptInfo).fontSize;
  591.         GetFNum ((**scriptInfo).fontName, &info->fontNum);
  592.         
  593.         HUnlock ((Handle) scriptInfo);
  594.  
  595.     } else {
  596.         err = ResError ();
  597.     } // if
  598.  
  599.     if (scriptInfo != NULL) {
  600.         ReleaseResource ((Handle) scriptInfo);
  601.     } // if
  602.  
  603.     return (ComponentResult) err;
  604.  
  605. } // GetScriptInfo
  606.  
  607. // ------------------------------------------------------------------------------------------------- 
  608.  
  609. static pascal ComponentResult
  610. GetInfo (CharsHandle* text, STHandle* style, ModalFilterUPP filter) {
  611.  
  612. #ifndef    __SC__
  613. #pragma unused (filter)
  614. #endif    // __SC__
  615.  
  616.     OSErr                err        = noErr;
  617.  
  618.     // This code is pretty cookie-cutter, unless you want to make it context-sensitive...
  619.  
  620.     do {
  621.     
  622.         *text = (CharsHandle) Get1Resource ('TEXT', kGetInfoRsrcID);
  623.         err = ResError ();
  624.         if (err != noErr) {
  625.             break;
  626.         } else if (*text == NULL) {
  627.             err = resNotFound;
  628.             break;
  629.         } // if
  630.         *style = (STHandle) Get1Resource ('styl', kGetInfoRsrcID);
  631.         err = ResError ();
  632.         if (err != noErr) {
  633.             break;
  634.         } else if (*style == NULL) {
  635.             err = resNotFound;
  636.             break;
  637.         } // if
  638.         DetachResource ((Handle) *text);
  639.         DetachResource ((Handle) *style);
  640.     
  641.     } while (false);    // execute once...
  642.     
  643.     return (ComponentResult) err;
  644.  
  645. } // GetInfo
  646.  
  647. // ------------------------------------------------------------------------------------------------- 
  648.  
  649. // The code needed to call a PPC code resource from 68K code (which is what the component is).
  650. OSErr Call_ResourcePPC (ResType pResType, short pResID, long params)
  651. {
  652.     Handle    resCodeHdl = Get1Resource(pResType,pResID);    // Get the resource
  653.     SInt32    result;
  654.     OSErr    myErr = noErr;
  655.     
  656.     if (resCodeHdl)                                    // Did we find it?
  657.     {
  658.         ResourceProcUPP    tResourceProcUPP;
  659.  
  660.         HLockHi(resCodeHdl);                        // Lock it high
  661.  
  662.         if (*(UInt16*) *resCodeHdl == _MixedModeMagic)    // If it's already a routine descriptor
  663.             tResourceProcUPP = (ResourceProcUPP) *resCodeHdl;    // just dereference it
  664.         else                                            // otherwise
  665.             tResourceProcUPP = NewResourceProcPPC(*resCodeHdl);    // create a routine descriptor
  666.  
  667.         result = CallResourceProc(tResourceProcUPP, params);// Call it
  668.  
  669.         if (*(UInt16*) *resCodeHdl != _MixedModeMagic)    // If it wasn't a routine descriptor
  670.             DisposeRoutineDescriptor(tResourceProcUPP);    // Dispose of the one we created
  671.  
  672.         HUnlock(resCodeHdl);                        // Unlock and
  673.         ReleaseResource(resCodeHdl);                // release the resource
  674.     }
  675.     else                                            // Didn't find it
  676.     {
  677.         myErr = ResError();                            // Get resource error
  678.         if (myErr == noErr)                            // If its noErr
  679.             myErr = resNotFound;                    // assume resource not found
  680.     }    
  681.     return myErr;                                    // return error
  682. }
  683.